package com.chenyue.cm.account.service.impl;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chenyue.cm.account.dao.JdAccountMapper;
import com.chenyue.cm.account.dao.JdAccountRecordMapper;
import com.chenyue.cm.account.dao.JdIntegralRecordMapper;
import com.chenyue.cm.account.domain.JdAccount;
import com.chenyue.cm.account.domain.JdAccountRecord;
import com.chenyue.cm.account.domain.JdAccountSource;
import com.chenyue.cm.account.domain.JdIntegralRecord;
import com.chenyue.cm.account.service.JdAccountService;
import com.chenyue.cm.account.vo.AccountSource;
import com.chenyue.cm.account.vo.ChangeType;
import com.chenyue.cm.base.dao.LcBaseMapper;
import com.chenyue.cm.base.service.BaseServiceImpl;
import com.chenyue.cm.common.constant.ConstantValues;
import com.chenyue.cm.common.dao.JdConstantValuesMapper;
import com.chenyue.cm.common.domain.JdConstantValues;
import com.chenyue.cm.user.domain.JdAppUser;
import com.chenyue.cm.utils.DateUtils;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * @author LBX
 */
@Service(value = "JdAccountService")
public class JdAccountServiceImpl extends BaseServiceImpl<JdAccount> implements JdAccountService {

    private final JdAccountRecordMapper accountRecordMapper;

    private final JdConstantValuesMapper constantValuesMapper;

    private final JdIntegralRecordMapper integralRecordMapper;

    @Resource
    private JdAccountMapper jdAccountMapper;




    public JdAccountServiceImpl(JdAccountRecordMapper accountRecordMapper, JdConstantValuesMapper constantValuesMapper,JdIntegralRecordMapper integralRecordMapper) {
        this.accountRecordMapper = accountRecordMapper;
        this.integralRecordMapper = integralRecordMapper;
        this.constantValuesMapper = constantValuesMapper;
    }

    @Override
    @Resource(name = "jdAccountMapper")
    public void setBaseMapper(LcBaseMapper<JdAccount, Serializable> baseMapper) {
        // TODO Auto-generated method stub
        this.baseMapper = baseMapper;
    }


    /**
     * 定时任务用 --- account
     */
    @Override
    public void autoMaticAccount(){
        //修改超时金币为失效金币
        JdAccountRecord record = new JdAccountRecord();
        record.setStatus(1);
        DateTime dateTime = DateUtil.offsetMonth(DateUtil.date(), -1);
        accountRecordMapper.update(record, new LambdaQueryWrapper<JdAccountRecord>()
                .le(JdAccountRecord::getCt,dateTime)
        );
    }



    /**
     * 账户余额 - new
     * @param userId
     * @return
     */
    @Override
    public JdAccount getAccount(int userId) {
        //修改超时金币为失效金币
        JdAccountRecord record = new JdAccountRecord();
        record.setStatus(1);
        DateTime dateTime = DateUtil.offsetMonth(DateUtil.date(), -1);
        accountRecordMapper.update(record, new LambdaQueryWrapper<JdAccountRecord>().eq(JdAccountRecord::getUserId,userId)
                .le(JdAccountRecord::getCt,dateTime).in(JdAccountRecord::getSource,AccountSource.DAILY_SIGN,AccountSource.GOLD_AWARD)
        );
        //查所有过期金币
        JdAccountRecord timePass = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId,userId)
                        .eq(JdAccountRecord::getChangeType,ChangeType.INCOME)
                        .eq(JdAccountRecord::getStatus,1)
                        .last("limit 1")
        );

        //查询有效金币总额
        JdAccountRecord income = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId, userId)
                        .eq(JdAccountRecord::getChangeType, ChangeType.INCOME)
                        .eq(JdAccountRecord::getStatus,0)
                        // .notIn(JdAccountRecord::getSource, AccountSource.MATCH_SIGN)
                        .last(" limit 1 ")
        );
        if (income == null) {
            income = new JdAccountRecord();
            income.setAmount(0D);
        }
        JdAccountRecord payment = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getChangeType, ChangeType.PAY)
                        .ne(JdAccountRecord::getSource, AccountSource.WITHDRAW)
                        .eq(JdAccountRecord::getUserId, userId)
                        // .eq(JdAccountRecord::getStatus,0)
                        .last(" limit 1 ")
        );
        if (payment == null) {
            payment = new JdAccountRecord();
            payment.setAmount(0D);
        }
        JdAccount jdAccount = jdAccountMapper.selectOne(new QueryWrapper<JdAccount>().lambda().eq(JdAccount::getUserId, userId).last(" limit 1 "));
        if (jdAccount == null) {
            jdAccount = createAccount(userId);
        }
//        填充实际金额
        final double left = (new BigDecimal(income.getAmount() + "").subtract(new BigDecimal(payment.getAmount() + "")).doubleValue());
        jdAccount.setAmount(left);
        jdAccountMapper.updateById(jdAccount);
        return jdAccount;
    }


    /**
     * 可提现金额 -- new
     * @param id
     * @return
     */
    @Override
    public Double withDrawal(int id) {
        //修改超时金币为失效金币
        JdAccountRecord record = new JdAccountRecord();
        record.setStatus(1);
        DateTime dateTime = DateUtil.offsetMonth(DateUtil.date(), -1);
        accountRecordMapper.update(record, new LambdaQueryWrapper<JdAccountRecord>().eq(JdAccountRecord::getUserId,id)
                .le(JdAccountRecord::getCt,dateTime)
        );

        return null;
    }

    /**
     * 创建账户
     *
     * @param userId 用户id
     * @return JdAccount
     */
    @Override
    public JdAccount createAccount(int userId) {
        JdAccount account = new JdAccount();
        account.setUserId(userId);
        account.setCt(DateUtil.date());
        int success = jdAccountMapper.insert(account);
        return success > 0 ? account : null;
    }

    /**
     * 查询用户余额
     *
     * @param id 用户id
     * @return 金币余额
     */
    @Override
    public JdAccount getAmount(Integer id) {
//        查询余额
        JdAccountRecord income = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId, id)
                        .eq(JdAccountRecord::getChangeType, ChangeType.INCOME)
                        .ne(JdAccountRecord::getSource, AccountSource.MATCH_SIGN)
                        .notIn(JdAccountRecord::getStatus,1)
                        .last(" limit 1 ")
        );
//        过期的签到金币
        JdAccountRecord signExpireCount = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId, id)
                        .eq(JdAccountRecord::getChangeType, ChangeType.INCOME)
                        .eq(JdAccountRecord::getSource, AccountSource.DAILY_SIGN)
//                        金币有效期一个月 小于当前时间 -1个月 = 过期
                        .lt(JdAccountRecord::getCt, DateUtil.offsetMonth(DateUtils.getToday(), -1))
                        .eq(JdAccountRecord::getStatus,0)
                        .last(" limit 1 ")
        );
        if (income == null) {
            income = new JdAccountRecord();
            income.setAmount(0D);
        }else {
            if (signExpireCount != null) {
                signExpireCount.setStatus(1);
                accountRecordMapper.updateById(signExpireCount);
                income.setAmount(income.getAmount() - signExpireCount.getAmount());
            }
        }
        JdAccountRecord payment = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getChangeType, ChangeType.PAY)
                        .ne(JdAccountRecord::getSource, AccountSource.WITHDRAW)
                        .eq(JdAccountRecord::getUserId, id)
                        .last(" limit 1 ")
        );
        if (payment == null) {
            payment = new JdAccountRecord();
            payment.setAmount(0D);
        }
        JdAccount jdAccount = jdAccountMapper.selectOne(new QueryWrapper<JdAccount>().lambda().eq(JdAccount::getUserId, id).last(" limit 1 "));
        if (jdAccount == null) {
            jdAccount = createAccount(id);
        }
//        填充实际金额
        final double left = (new BigDecimal(income.getAmount() + "").subtract(new BigDecimal(payment.getAmount() + "")).doubleValue());
        jdAccount.setAmount(left);
        return jdAccount;
    }

    /**
     * 查询用户积分
     *
     * @param id 用户id
     * @return 积分余额
     */
    @Override
    public JdAccount getIntergnal(Integer id) {
        return lambdaQuery().eq(JdAccount::getUserId, id).one();
    }




    /**
     * 账户变动-充值
     *
     * @param userId  账户id
     * @param amount  充值金额
     * @param source  变动来源
     * @param orderId 订单号
     * @return 错误信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String recharge(Integer userId, double amount, int source, Integer orderId) {
//        获取余额
        JdAccount account = getAmount(userId);
//        创建记录
        JdAccountRecord record = new JdAccountRecord();
        record.setAmount(amount);
        record.setUserId(userId);
//        收入
        record.setChangeType(ChangeType.INCOME);
        record.setOrderId(orderId);
        record.setSource(source);
        //时效
        record.setStatus(0);
        record.setCt(Calendar.getInstance().getTime());
        int insert = accountRecordMapper.insert(record);
        account.setEt(Calendar.getInstance().getTime());
//        更新余额
        account.setAmount(amount + account.getAmount());
        int i = jdAccountMapper.updateByPrimaryKey(account);
        return insert > 0 && i > 0 ? "" : "充值失败";
    }

    /**
     * 账户变动-消费
     *
     * @param userId  账户id
     * @param amount  消费金额
     * @param source  变动来源
     * @param orderId 订单号
     * @return 错误信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String costume(Integer userId, double amount, int source, Integer orderId) {
//        获取余额
        JdAccount account = getAccount(userId);
        if (account.getAmount() - amount < 0) {
            return "余额不足";
        }
//        获取签到金币 未过期金币可以抵扣
        JdAccountRecord signCount = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId, userId)
                        .eq(JdAccountRecord::getChangeType, ChangeType.INCOME)
                        .eq(JdAccountRecord::getSource, AccountSource.DAILY_SIGN)
                        .gt(JdAccountRecord::getCt, DateUtil.offsetMonth(DateUtils.getToday(), -1))
                        .notIn(JdAccountRecord::getStatus, 1)
                        .last(" limit 1 ")
        );
        if (signCount != null) {
            if (signCount.getAmount() > 0) {
                JdAccountRecord record = new JdAccountRecord();
                record.setAmount(amount);
                record.setUserId(userId);
//                抵扣的金币用来持平记录
                record.setChangeType(ChangeType.PASS_INCOME);
                record.setOrderId(orderId);
                record.setSource(AccountSource.GOLD_RECHARGE);
                record.setCt(Calendar.getInstance().getTime());
                accountRecordMapper.insert(record);
            }
        }
        JdAccountRecord record = new JdAccountRecord();
        record.setAmount(amount);
        record.setUserId(userId);
//        消费
        record.setChangeType(ChangeType.PAY);
        record.setOrderId(orderId);
        record.setSource(source);
        record.setCt(Calendar.getInstance().getTime());
        int insert = accountRecordMapper.insert(record);
        account.setEt(Calendar.getInstance().getTime());
//        扣费
        account.setAmount(account.getAmount() - amount);
        int i = jdAccountMapper.updateByPrimaryKey(account);
        return insert > 0 && i > 0 ? "" : "消费失败";
    }

    /**
     * 获取可提现金额
     *
     * @param id 用户id
     * @return 金额
     */
    @Override
    public Double getWithdrawAbleAmount(Integer id) {
        JdAccountRecord income = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getUserId, id)
                        .eq(JdAccountRecord::getChangeType, ChangeType.INCOME)
                        .eq(JdAccountRecord::getSource, AccountSource.MATCH_SIGN)
                        .last(" limit 1 ")
        );

        JdAccountRecord payment = accountRecordMapper.selectOne(
                new QueryWrapper<JdAccountRecord>()
                        .select("sum(amount) as amount")
                        .lambda()
                        .eq(JdAccountRecord::getChangeType, ChangeType.PAY)
                        .eq(JdAccountRecord::getSource, AccountSource.WITHDRAW)
                        .eq(JdAccountRecord::getUserId, id)
                        .last(" limit 1 ")
        );
        if (income == null) {
            return 0D;
        }
        if (payment != null) {
            final double amount = income.getAmount() - payment.getAmount();
            income.setAmount(amount > 0 ? amount : 0);
        }
        Wrapper<JdConstantValues> wrapper = new QueryWrapper<JdConstantValues>()
                .lambda().eq(JdConstantValues::getConstantKey, ConstantValues.EXCHANGE_RATE).last(" limit 1 ");
//        获取金币汇率
        final JdConstantValues constantValues = constantValuesMapper.selectOne(wrapper);
        final String exchangeRate = constantValues.getConstantValue();
        return income.getAmount() / Integer.parseInt(exchangeRate);
    }


    /**
     * 账户变动-积分获取
     *
     * @param userId  账户id
     * @param integral  账户积分
     * @param source  变动来源
     * @param orderId 订单号
     * @return 错误信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String integralRecharge(Integer userId,int  integral, int source,String orderId,String remark) {
//        获取余额
        JdAccount account = getIntergnal(userId);
//        创建记录
        JdIntegralRecord record = new JdIntegralRecord();
        record.setIntegral(integral);
        record.setUserId(userId);
//        收入
        record.setChangeType(ChangeType.INCOME);
        record.setSource(source);
        record.setOrderId(orderId);
        record.setRemark(remark);
        record.setCt(Calendar.getInstance().getTime());
        int insert = integralRecordMapper.insert(record);
        account.setEt(Calendar.getInstance().getTime());
//        更新余额
        account.setIntegral(integral + account.getIntegral());
        int i = jdAccountMapper.updateByPrimaryKey(account);
        return insert > 0 && i > 0 ? "" : "充值失败";
    }

    /**
     * 账户变动-消费
     *
     * @param userId  账户id
     * @param integral  账户积分
     * @param source  变动来源
     * @param orderId 订单号
     * @return 错误信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String integralCostume(Integer userId, int  integral, int source, String orderId) {
//        获取余额
        JdAccount account = getIntergnal(userId);
        if (account.getIntegral() - integral < 0) {
            return "余额不足";
        }

        JdIntegralRecord record = new JdIntegralRecord();
        record.setIntegral(integral);
        record.setUserId(userId);
//        消费
        record.setChangeType(ChangeType.PAY);
        record.setOrderId(orderId);
        record.setSource(source);
        record.setCt(Calendar.getInstance().getTime());
        record.setRemark("积分商城兑换");
        int insert = integralRecordMapper.insert(record);
        account.setEt(Calendar.getInstance().getTime());
//        扣费
        account.setIntegral(account.getIntegral() - integral);
        int i = jdAccountMapper.updateById(account);
        return insert > 0 && i > 0 ? "" : "消费失败";
    }

    @Override
    public List<JdIntegralRecord> selectByType(JdAppUser user, Integer type) {
        if (type == 0) {
            return integralRecordMapper.selectList(Wrappers.<JdIntegralRecord>lambdaQuery().eq(JdIntegralRecord::getUserId, user.getId()).orderByDesc(JdIntegralRecord::getCt));
        } else if (type == 1) {
            return integralRecordMapper.selectList(Wrappers.<JdIntegralRecord>lambdaQuery().eq(JdIntegralRecord::getChangeType, ChangeType.INCOME).eq(JdIntegralRecord::getUserId, user.getId()).orderByDesc(JdIntegralRecord::getCt));
        } else if (type == 2) {
            return integralRecordMapper.selectList(Wrappers.<JdIntegralRecord>lambdaQuery().eq(JdIntegralRecord::getChangeType, ChangeType.PAY).eq(JdIntegralRecord::getUserId, user.getId()).orderByDesc(JdIntegralRecord::getCt));
        }
        return new ArrayList<>();
    }



}
